﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Web.SessionState;
using System.Configuration;
namespace HNQXYJ.DAL
{
    public class SocketListen
    {
       static Thread threadWatch = null;//负责监听客户端连接请求的线程
       static Socket sokWatch = null;//负责监听客户端请求的套接字
       static bool Flage = false;
       static Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
       static Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
       
       
        /// <summary>
        /// 开启监听的方法入口
        /// </summary>
       public static void BtnBeinListen(string Ip,int Port)
       {
           IPAddress address = IPAddress.Parse(Ip);
           IPEndPoint endpoint = new IPEndPoint(address, Port);
           sokWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
           sokWatch.Bind(endpoint);
           sokWatch.Listen(30);
           threadWatch = new Thread(WatchConnectioning);
           threadWatch.IsBackground = true;
           threadWatch.Start();
           Flage = true;
       }

       /// <summary>
       /// 监听客户端请求的方法
       /// </summary>
       static void WatchConnectioning()
       {
           while (true)
           {
               try
               {
                   Socket sokConnetion = sokWatch.Accept();
                   Thread thr = new Thread(RecMsg);
                   thr.IsBackground = true;
                   thr.Start(sokConnetion);
               }
               catch (Exception ex)
               {
                  //有异常，但是在此不作处理 
                  
               }

           }
 
       }

       static string strMsgRec = "";
       // 接收客户端发来数据的方法
       static void RecMsg(object socketClientPara)
       {
           Socket sockClient = socketClientPara as Socket;
           string phoneKey = "";
           while (true)
           {
              
              // string strMsgRec = "";
               byte[] arrMsgRec = new byte[1024 * 1024 * 2];
               int length = -1;
               sockClient.ReceiveTimeout = 360000;//心跳间隔设置为7分钟
               try
               {
                   //将从客户端接受到的数据存入字节数组中，并返回数组的实际长度
                   length = sockClient.Receive(arrMsgRec);
                   strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length);
                   char strHeader = strMsgRec[0];
                   phoneKey = strMsgRec.Substring(2, 11);

                   //处理客户端发送的心跳包
                   if (strHeader == 'R')//正常，表示客户端在线的情况
                   {

                       //套接字字典中如果没有该套接字（第一次连接或者是断开后重新连接） 就添加进去
                       if (!dict.ContainsKey(phoneKey))
                       {
                           dict.Add(phoneKey, sockClient);
                       }
                       else
                       {
                           dict[phoneKey] = sockClient;
                       }
                       //此时更新终端表中改终端的状态为 在线
                       UpdateTerminalStatus(phoneKey, "在线");
                   }
                   else if (strHeader == 'D')//发送信息成功后的返回数据
                   {
                       //此处要往数据库的信息表中添加数据，记录数据发送是否成功。
                       // UpdateNewTerminalStatus(phoneKey, "0");
                   }
                   else if (strHeader == 'P')
                   {
                       UpdateTerminalStatus(phoneKey, "离线");
 
                   }
                   
               }

               catch (SocketException ex)
               {
                   //出现异常，终端掉线
                   UpdateTerminalStatus(phoneKey, "离线");
                   dict.Remove(phoneKey);
                   break;
 
               }
               catch (Exception ex)
               {
                   //出现异常，终端掉线
                   UpdateTerminalStatus(phoneKey, "离线");
                   dict.Remove(phoneKey);
                   break;

               }
           }
 
       }

        /// <summary>
        /// 向指定终端发送信息
        /// </summary>
        /// <param name="list">终端列表</param>
        /// <param name="msg">要发送的信息</param>
        /// <param name="sendTimes">发送次数</param>
       public static void BtnSendMsgToAll(List<string> list,string sessionName, string msg, string sendTimes,string ranklevel)
       {
           string header = "D 12345678";
           string strMsg = header + sendTimes + msg;
           byte[] arrMsg = System.Text.Encoding.GetEncoding("gb2312").GetBytes(strMsg);

           for (int i = 0; i < list.Count; i++)
           {
               if (dict.ContainsKey(list[i]))
               {
                   dict[list[i]].Send(arrMsg);
                   //成功发送信息的同时要向历史信息表中插入数据
                   InsertIntoHistoryInfor(list[i],sessionName, msg, "成功",ranklevel);
               }
               else
               {
                   //信息发送失败
                   InsertIntoHistoryInfor(list[i], sessionName, msg, "失败", ranklevel);
               }
           }
       }

       /// <summary>
       /// 开启监听
       /// </summary>
       public static void StartListen(string Ip,int Port)
       {
           if (Flage)
           {
               return;
           }
           else
           {
              // BtnBeinListen(Ip, Port);
           }
       }

        /// <summary>
        /// 终止监听
        /// </summary>
       public static void EndListen()
       {
           Flage = false;
           sokWatch.Close();
           threadWatch.Abort();
       }

       //更新数据库状态
        static void  UpdateTerminalStatus(string phonekey,string status)
        {
            //更新终端表状态的操作
            string procName = "TerminalUpdateStatusByPhone";
            SqlParameter[] paras ={
                                   new SqlParameter("@Phone",SqlDbType.VarChar,50),
                                   new SqlParameter("@Statuss",SqlDbType.NVarChar,50)
                               };
            paras[0].Value = phonekey;
            paras[1].Value = status;
            int res = SqlHelper.ExecNonQuery(procName, paras);
            
        }

        /// <summary>
        /// 在历史信息表中记录信息情况
        /// </summary>
        /// <param name="phone"></param>
        /// <param name="msg"></param>
        /// <param name="flage"></param>

        static int InsertIntoHistoryInfor(string phone,string sessionName,string msg,string flage,string ranklevel)
        {
            //string username =sessionName;
            //DateTime dt = DateTime.Now;
           
            ////写数据库的操作
            //string procName = "HistoryInforInsertSendMsg";
            //SqlParameter[] paras ={
            //                     new SqlParameter("@Phone",SqlDbType.NVarChar,50),
            //                     new SqlParameter("@UserName",SqlDbType.NVarChar,50),
            //                     new SqlParameter("@Information",SqlDbType.NVarChar,500),
            //                     new SqlParameter("@IsSuccess",SqlDbType.NVarChar,50)
            //                     };
            //paras[0].Value = phone; 
            //paras[1].Value = username;
            //paras[2].Value = msg;
            //paras[3].Value = flage;

            //int res = TerminalDAL.ExecNonQuery(procName, paras);
            int res = HistoryInforDAL.InsertDataMessage(phone,sessionName,msg,flage,ranklevel);
            return res;
        }

    }
}